package me.zhengjie.ppService;

import cn.hutool.core.util.ObjectUtil;
import lombok.RequiredArgsConstructor;
import me.zhengjie.Enum.InBoundType;
import me.zhengjie.modbusTCP.EntranceTCP;
import me.zhengjie.pojo.sqlServer.*;
import me.zhengjie.modbusTCP.PalletTCP;
import me.zhengjie.repository.*;
import me.zhengjie.service.PPInventoryService;
import me.zhengjie.service.PPStorageService;
import me.zhengjie.service.PPTimeConfigService;
import me.zhengjie.service.dto.PPOutBoundDto;
import me.zhengjie.util.AnalyseCodeScannerUtil;
import me.zhengjie.util.UniqueCodeUtil;
import me.zhengjie.utils.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.util.ObjectUtils;

import javax.transaction.Transactional;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @Author: xinglin
 * @CreateTime: 2024-08-14
 * @Description: 读取载盘编号
 * @Version: 1.0
 */


@Component
@RequiredArgsConstructor
public class PpPalletService {


    private final PpPalletRepository ppPalletRepository;
    private final PPInfoRepository ppInfoRepository;
    private final EntranceTCP entranceTCP;
    private final PPStorageService ppStorageService;
    private final PPStorageRepository ppStorageRepository;
    private final PPOutboundMissionRepository ppOutboundMissionRepository;
    private final PPTaskResultRepository ppTaskResultRepository;
    private final PPStationRepository ppStationRepository;
    private final PPInBoundService ppInBoundService;
    private final PPInventoryRepository  ppInventoryRepository;
    private final PPTimeConfigService ppTimeConfigService;




    private final Logger ppLog = LoggerFactory.getLogger("pp");

    public PpPallet findByPalletCode(String palletCode) {
        return ppPalletRepository.findByPalletCode(palletCode);
    }

    /**
     * 获取入库的载盘编号
     * @param stationCode
     * @return
     */
    public String getPalletCode(String stationCode) {

        Map<String, String> palletCodeMap = new HashMap<>();


//        // 使用数组存储入口的配置
//        int[] entrances = {
//                RegisterAddressConfig.p2_4station1,
//                RegisterAddressConfig.p2_14station2,
//                RegisterAddressConfig.p2_15station3,
//                RegisterAddressConfig.p2_16station4,
//                RegisterAddressConfig.p2_17station5,
//                RegisterAddressConfig.p2_18station6,
//                RegisterAddressConfig.p2_4station1,
//                RegisterAddressConfig.p2_1station7,
//                RegisterAddressConfig.p2_5station8,
//                RegisterAddressConfig.p2_6station9
//        };
//
//        // 使用对应的站点代码
//        String[] stationCodes = {
//                "inbound_station1","inbound_station2",
//                "inbound_station3","inbound_station4",
//                "inbound_station5","inbound_station6",
//                "outbound_station1","outbound_station7",
//                "outbound_station8","outbound_station9"
//        };

//        for (int i = 0; i < entrances.length; i++) {
//            try {
//                String palletCode = String.valueOf(palletTCP.readHoldingRegisters(entrances[i]));
//                if (palletCode != null) {
//                    palletCodeMap.put(stationCodes[i], palletCode);
//                } else {
//                    ppLog.warn("工作站收到载盘码为null: {}", stationCodes[i]);
//                }
//            } catch (Exception e) {
//                ppLog.error("读取载盘码PLC寄存器信息失败 {}: {}", entrances[i], e.getMessage());
//            }
//        }

        for (InBoundType inBoundType : InBoundType.values()) {
            try {
                String firstCode = entranceTCP.readHoldingRegistersString(inBoundType.getPpInBoundAllowGroup().getReadPpPalletAddressA());
                String secondCode = entranceTCP.readHoldingRegistersString(inBoundType.getPpInBoundAllowGroup().getReadPpPalletAddressB());

                if (firstCode != null && secondCode != null) {
                    String palletCode = AnalyseCodeScannerUtil.analyseCodeScanner(firstCode, secondCode);
                    switch (inBoundType.getPpInBoundAllowGroup().getStationCode()) {
                        case "AInBound2":
                            entranceTCP.write(InBoundType.P2_5.getPpInBoundAllowGroup().getSuccessfulReadCode(),1,5);
                            break;
                        case "AInBound3":
                            entranceTCP.write(InBoundType.P2_6.getPpInBoundAllowGroup().getSuccessfulReadCode(),1,5);
                            break;
                        case "AOutBound2":
                            entranceTCP.write(InBoundType.P2_14.getPpInBoundAllowGroup().getSuccessfulReadCode(),1,5);
                            break;
                        case "AOutBound3":
                            entranceTCP.write(InBoundType.P2_15.getPpInBoundAllowGroup().getSuccessfulReadCode(),1,5);
                            break;
                        case "AOutBound4":
                            entranceTCP.write(InBoundType.P2_16.getPpInBoundAllowGroup().getSuccessfulReadCode(),1,5);
                            break;
                        case "AOutBound5":
                            entranceTCP.write(InBoundType.P2_17.getPpInBoundAllowGroup().getSuccessfulReadCode(),1,5);
                            break;
                        case "AOutBound6":
                            entranceTCP.write(InBoundType.P2_18.getPpInBoundAllowGroup().getSuccessfulReadCode(),1,5);
                            break;

                    }
                    palletCodeMap.put(inBoundType.getPpInBoundAllowGroup().getStationCode(), palletCode);
                }
            } catch (Exception e) {
                ppLog.error("读取载盘码PLC寄存器信息失败 {}: {}",inBoundType.getPpInBoundAllowGroup().getStationCode(), e.getMessage());
            }
        }

        return palletCodeMap.get(stationCode);

    }



    //解绑载盘
    @Transactional
    public void unBindPallet(String palletCode){
//        PpPallet ppPallet= ppPalletRepository.findByPalletCode(palletCode);
//        ppPallet.setPpBatch(null);
//        ppPalletRepository.save(ppPallet);

        ppPalletRepository.unBindPallet(palletCode);

    }

    //找合适的载盘出库
    @Transactional
    public void outBoundPallet(PPOutBoundDto ppOutBoundDto){
        PPStorage ppStorage = new PPStorage();

//        PpPallet ppPallet = ppPalletRepository.findByPpBatch(ppOutBoundDto.getPpBatch());
        PpPallet ppPallet = ppPalletRepository.findByPalletCode(ppOutBoundDto.getPalletCode());

        if (ObjectUtil.isNotEmpty(ppPallet)) {
            ppStorage = ppStorageRepository.findPPStorageByPalletCode(ppPallet.getPalletCode());
        }else {
            //查找合适的空载盘
            if (!ppStorageRepository.findSuitableOutNullPalletPPStorage().isEmpty()) {
                ppStorage = ppStorageRepository.findSuitableOutNullPalletPPStorage()
                        .stream().filter(storage -> StringUtils.isNotBlank(storage.getPalletCode())).findFirst().get();
            } else {
                throw new RuntimeException("没有合适的载盘");
            }
        }

        //查看出库任务有无相同托盘的任务
        if (ObjectUtil.isNotEmpty(ppOutboundMissionRepository.findPPOutboundMissionByPalletCode(ppOutBoundDto.getPalletCode()))) {
            ppLog.error("托盘{}有出库任务,请勿重复执行入库",ppOutBoundDto.getPalletCode());
             throw new RuntimeException(ppOutBoundDto.getPalletCode()+"该托盘有出库任务,请勿重复执行出库");
        }

        // 查看这个工作站是否已经存在空托盘出库任务
        ppOutboundMissionRepository
                .findPPOutboundMissionsByDestination(ppOutBoundDto.getStationCode())
                .forEach(outboundMission -> {
                    if (ObjectUtil.isEmpty(outboundMission.getPpId()) && ppStationRepository.findByStationCode(ppOutBoundDto.getStationCode()).getStationType() == 0) {
                        throw new RuntimeException("该工作站已经存在空载盘出库任务，请勿重复点击");
                    }
                });

        PPTaskResult taskResult = ppTaskResultRepository.findPPTaskResultByToLocation(ppOutBoundDto.getStationCode());
        if (ObjectUtil.isNotEmpty(taskResult)) {
            if (ppStorageRepository.findPPStorageByPalletCode(taskResult.getLpnCode()).getLocationInventoryStatus() == 0 && ppStationRepository.findByStationCode(ppOutBoundDto.getStationCode()).getStationType() == 0) {
                throw new RuntimeException("该工作站已经存在空载盘出库任务，请勿重复点击");
            }
        }

        // 站点状态
        PPStation ppStation = ppStationRepository.findByStationCode(ppOutBoundDto.getStationCode());
        if (ppStation.getTakeStatus() == 1 && ppStation.getStationType() == 0){
            throw new RuntimeException("该工作站已有载盘，请勿重复空载盘出库");
        }

        //锁储位
        ppStorageRepository.lockStorage(ppStorage.getStorageCode());

        //创建出库任务
        String palletCode = ppStorage.getPalletCode();
        PPOutboundMission ppOutBoundMission = new PPOutboundMission();
        ppOutBoundMission.setMissionCode(UniqueCodeUtil.createCode());
        ppOutBoundMission.setOutBoundOrderId(null);
        ppOutBoundMission.setPriority(0);
        ppOutBoundMission.setMissionStatus(1);
        ppOutBoundMission.setPalletCode(palletCode);

        // 查找储位
        Integer storageId = ppInventoryRepository.findStorageIdByPalletCode(palletCode);
        String storageCode = ppStorageService.findStorageCodeById(storageId);

        // 设置起点和终点
        ppOutBoundMission.setSource(storageCode);
        ppOutBoundMission.setDestination(ppOutBoundDto.getStationCode());
        ppOutBoundMission.setCreateTime(LocalDateTime.now());

        //保存出库任务
        ppOutboundMissionRepository.save(ppOutBoundMission);
//        List<PPOutboundMission> ppOutboundMissions = new ArrayList<>();
//        ppOutboundMissions.add(ppOutBoundMission);
//        ppOutBoundService.createOutTask(ppOutboundMissions);

    }


    //空载盘入库
    @Transactional
    public void inBoundPallet(String palletCode,String stationCode){
        if (ObjectUtils.isEmpty(this.findByPalletCode(palletCode))) {
                /*//如果没有就插入新的载盘
//                PpPallet newpallet = new PpPallet();
//                newpallet.setPalletCode(nullPalletDto.getPalletCode());
//                newpallet.setCreateTime(LocalDateTime.now());
                return Resp.builder().status(503).msg("该载盘码没有记录，无法进行空载盘入库").build();*/
            PpPallet ppPallet = new PpPallet();
            ppPallet.setPalletCode(palletCode);
            ppPallet.setCreateTime(LocalDateTime.now());
            this.savePallet(ppPallet);

        }

        if (ObjectUtils.isEmpty(ppStorageService.findPPStorageByPalletCode(palletCode))) {

//            PpPallet ppPallet = ppPalletRepository.findByPalletCode(palletCode);

            //解绑载盘
            ppPalletRepository.unBindPallet(palletCode);

            //创建空载具入库任务
            ppInBoundService.createInboundMission(palletCode, stationCode);

//            //空载盘回库要删除对应的库存信息
//            ppInventoryRepository.deletePPInventoryByPalletCode(palletCode);
//
//            ppLog.info("空载盘"+"回库，删除对应的库存",palletCode);
//
//            //删除对应的pp_config
//            ppTimeConfigService.deleteByPpBatch(ppPallet.getPpBatch());



        } else {
            throw new RuntimeException("该载盘已在储位中");
        }


    }

    /**
     * 根据载盘码获取ppInfo
     */
    public PPInfo getPpInfoByPalletCode(String palletCode){
        String ppBatch= ppPalletRepository.findPpBatchByPalletCode(palletCode);
        return ppInfoRepository.getPPInfoByPpBatch(ppBatch);
    }

    @Transactional
    public void savePallet(PpPallet ppPallet){
        ppPalletRepository.saveAndFlush(ppPallet);
    }

}
